home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / comms / pipeln10.zip / AQUEDUCT.ASM next >
Assembly Source File  |  1990-06-01  |  12KB  |  386 lines

  1. ;**************************************************************************
  2. ;*     AQUEDUCT vers 1.20, DOS                                            *
  3. ;*     Connects COM1 and COM2 in software.                                *
  4. ;*     6/1/90                                                             *
  5. ;*     by James W. Birdsall                                               *
  6. ;*                                                                        *
  7. ;*     assembles under Turbo Assembler 1.0, 2.0                           *
  8. ;*                                                                        *
  9. ;*     requires DOS 2.0 or higher                                         *
  10. ;*                                                                        *
  11. ;*   This program is a small TSR that connects COM1 and COM2 in software. *
  12. ;*   It is run from the command line with no arguments. After             *
  13. ;*   installation, setup and activation is performed with the program     *
  14. ;*   VALVE.                                                               *
  15. ;*                                                                        *
  16. ;*   This program can share an interrupt vector. It can be set to chain   *
  17. ;*   to the previous interrupt handler if examination of the serial port  *
  18. ;*   shows that no interrupt is pending.                                  *
  19. ;*                                                                        *
  20. ;**************************************************************************
  21.  
  22. LOCALS
  23. .MODEL tiny
  24.  
  25.  
  26. ENVOFFSET    EQU    2Ch
  27.  
  28. INTERFACEINT    EQU    0F1h
  29.  
  30. BUFFERLENGTH    EQU    8
  31. BUFFERLENMASK    EQU    08h
  32. BUSY1READ       EQU     01h
  33. BUSY1SEND    EQU     02h
  34. BUSY2READ    EQU    04h
  35. BUSY2SEND    EQU    08h
  36.  
  37.  
  38. ; TO CHANGE FROM COM1 OR COM2, CHANGE THE FOLLOWING INTERRUPT AND PORT
  39. ; VALUES.
  40. COM1INT        EQU    0Ch
  41. COM2INT        EQU    0Bh
  42.  
  43. COM1BASE    EQU    3F8h
  44. COM1IER        EQU    3F9h
  45. COM1IIR        EQU    3FAh
  46. COM1LSR        EQU    3FDh
  47.  
  48. COM2BASE    EQU    2F8h
  49. COM2IER        EQU    2F9h
  50. COM2IIR        EQU    2FAh
  51. COM2LSR        EQU    2FDh
  52. ; END OF INTERRUPT AND PORT VALUES
  53.  
  54.  
  55. EOI        EQU    20h
  56. EOIPORT        EQU    20h
  57.  
  58. RDAINT        EQU    04h
  59. THREINT        EQU    02h
  60. RDAENABLE    EQU    01h
  61. BOTHENABLE    EQU    03h
  62. OVERRUNMASK    EQU    02h
  63. INTPENDMASK    EQU    01h
  64.  
  65.  
  66. .CODE
  67.     ORG    100h
  68. start:
  69.     jmp    Install            ; jump to installation code
  70.  
  71. ; DATA AREA
  72.  
  73. errors        dw    0
  74. int_B        dd    0
  75. old_int_B    dd    0
  76. int_C        dd    0
  77. old_int_C    dd    0
  78. PSPseg        dw    0
  79. old_interface    dd    0
  80. enabled         db      0
  81. chain        db    0
  82. one_in_head    dw    0
  83. one_in_tail    dw    0
  84. two_in_head    dw    0
  85. two_in_tail    dw    0
  86. busyflag        db      0
  87. one_in        db    BUFFERLENGTH dup (?)
  88. two_in        db    BUFFERLENGTH dup (?)
  89.  
  90.  
  91. ; HANDLER FOR COM1 INTERRUPTS
  92.  
  93. Com1handler:
  94.     sti                ; enable interrupts
  95.         push    ax            ; preserve
  96.         push    bx
  97.         push    dx
  98.  
  99.         mov    dx, COM1LSR        ; check for overruns
  100.         in    al, dx
  101.         test    al, OVERRUNMASK
  102.         jz    @@NoOverrun        ; if zero, OK
  103.         inc    cs:errors        ; else increment ERRORS
  104. @@NoOverrun:
  105.     mov    dx, COM1IIR        ; read interrupt id
  106.         in    al, dx
  107.         test    al, INTPENDMASK        ; is our interrupt?
  108.         jz    @@Ours            ; if zero, ours
  109.         jmp    @@NotOurs        ; else not
  110. @@Ours:
  111.         cmp    al, RDAINT        ; is received char?
  112.         je    @@Received
  113.         cmp    al, THREINT        ; is send?
  114.         je    @@Transmit
  115.         jmp    @@SendEOI        ; if unknown, send EOI
  116.  
  117. @@Received:
  118.     mov    dx, COM1BASE        ; read character
  119.         in    al, dx
  120.     test    cs:busyflag, BUSY2SEND    ; is port 2 sending?
  121.         jz    @@OkToRead        ; if zero, go ahead
  122.         inc    cs:errors        ; else increment errors
  123.         jmp    @@SendEOI        ; and send EOI
  124. @@OkToRead:
  125.     or    cs:busyflag, BUSY1READ    ; set flag
  126.         mov    bx, cs:one_in_head    ; get index
  127.         mov    cs:one_in + bx, al    ; put char in buffer
  128.         inc    cs:one_in_head            ; increment index
  129.         test    cs:one_in_head, BUFFERLENMASK    ; check for index overflow
  130.         jz    @@ReadDone            ; if no overflow, jump
  131.         mov    cs:one_in_head, 0    ; else zero index
  132. @@ReadDone:
  133.         mov    dx, COM2IER        ; read interrupt enable
  134.         in    al, dx
  135.         cmp    al, BOTHENABLE        ; THRE already on?
  136.         je    @@ReadDone2        ; do nothing
  137.         mov    al, BOTHENABLE        ; else enable it
  138.         xor     cs:busyflag, BUSY1READ  ; reset flag just before enabling int
  139.         out    dx, al
  140.         jmp    @@SendEOI        ; and jump
  141. @@ReadDone2:
  142.     xor    cs:busyflag, BUSY1READ    ; reset flag
  143.         jmp    @@SendEOI
  144.  
  145. @@Transmit:
  146.     test    cs:busyflag, BUSY2READ    ; is port 2 reading?
  147.         jz    @@OkToSend        ; if zero, go ahead
  148.         or      cs:busyflag, BUSY1SEND
  149.         jmp    @@NoTrans        ; otherwise shut down sending
  150. @@OkToSend:
  151.     or    cs:busyflag, BUSY1SEND    ; set flag
  152.         mov    bx, cs:two_in_tail    ; set index
  153.         cmp    bx, cs:two_in_head    ; are chars to send?
  154.         je    @@NoTrans        ; if not, shut down sending
  155.         mov    al, cs:two_in + bx    ; else move char to AL
  156.         mov    dx, COM1BASE
  157.         out    dx, al
  158.         inc    cs:two_in_tail            ; increment index
  159.         test    cs:two_in_tail, BUFFERLENMASK    ; check for overflow
  160.         jz    @@SentOK            ; if no overflow, jump
  161.         mov    cs:two_in_tail, 0    ; else zero index
  162. @@SentOK:
  163.     xor    cs:busyflag, BUSY1SEND    ; reset flag
  164.         jmp    @@SendEOI
  165. @@NoTrans:
  166.     mov    dx, COM1IER        ; read interrupt enable
  167.         in    al, dx
  168.         cmp    al, RDAENABLE        ; RDA only already?
  169.         je    @@NoTrans2        ; if so, do nothing
  170.         mov    al, RDAENABLE        ; else enable RDA only
  171.         out    dx, al
  172.         jmp    @@NoTrans2        ; and jump
  173. @@NoTrans2:
  174.     xor    cs:busyflag, BUSY1SEND    ; reset flag
  175.         jmp    @@SendEOI        ; and jump
  176.  
  177. @@NotOurs:
  178.     test    cs:chain, 0FFh        ; is chain zero?
  179.         jz    @@SendEOI        ; if so, return normally
  180.         pushf                ; preserve flags
  181.         call    cs:old_int_C        ; call old handler
  182.         jmp    @@Final            ; and return
  183.  
  184. @@SendEOI:
  185.     mov    al, EOI            ; send EOI
  186.         out    EOIPORT, al
  187.  
  188. @@Final:
  189.     pop    dx            ; restore
  190.         pop    bx
  191.         pop    ax
  192.         iret                ; return
  193.  
  194.  
  195. ; HANDLER FOR COM2 INTERRUPTS
  196.  
  197. Com2handler:
  198.     sti                ; enable interrupts
  199.         push    ax            ; preserve
  200.         push    bx
  201.         push    dx
  202.  
  203.         mov    dx, COM2LSR        ; check for overruns
  204.         in    al, dx
  205.         test    al, OVERRUNMASK
  206.         jz    @@NoOverrun        ; if zero, OK
  207.         inc    cs:errors        ; else increment ERRORS
  208. @@NoOverrun:
  209.     mov    dx, COM2IIR        ; read interrupt id
  210.         in    al, dx
  211.         test    al, INTPENDMASK        ; is our interrupt?
  212.         jz    @@Ours            ; if zero, ours
  213.     jmp    @@NotOurs        ; else not
  214. @@Ours:
  215.         cmp    al, RDAINT        ; is received char?
  216.         je    @@Received
  217.         cmp    al, THREINT        ; is send?
  218.         je    @@Transmit
  219.         jmp    @@SendEOI        ; if unknown, send EOI
  220.  
  221. @@Received:
  222.     mov    dx, COM2BASE        ; read character
  223.         in    al, dx
  224.     test    cs:busyflag, BUSY1SEND    ; is port 1 sending?
  225.         jz    @@OkToRead        ; if zero, go ahead
  226.         inc    cs:errors        ; else increment errors
  227.         jmp    @@SendEOI        ; and send EOI
  228. @@OkToRead:
  229.     or    cs:busyflag, BUSY2READ    ; set flag
  230.         mov    bx, cs:two_in_head    ; get index
  231.         mov    cs:two_in + bx, al    ; put char in buffer
  232.         inc    cs:two_in_head            ; increment index
  233.         test    cs:two_in_head, BUFFERLENMASK    ; check for index overflow
  234.         jz    @@ReadDone            ; if no overflow, jump
  235.         mov    cs:two_in_head, 0    ; else zero index
  236. @@ReadDone:
  237.         mov    dx, COM1IER        ; read interrupt enable
  238.         in    al, dx
  239.         cmp    al, BOTHENABLE        ; THRE already on?
  240.         je    @@ReadDone2        ; do nothing
  241.         mov    al, BOTHENABLE        ; else enable it
  242.         out    dx, al
  243.         jmp    @@ReadDone2        ; and jump
  244. @@ReadDone2:
  245.     xor    cs:busyflag, BUSY2READ    ; reset flag
  246.         jmp    @@SendEOI        ; and jump
  247.  
  248. @@Transmit:
  249.     test    cs:busyflag, BUSY1READ    ; is port 1 reading?
  250.         jz    @@OkToSend        ; if zero, go ahead
  251.         or    cs:busyflag, BUSY2SEND    ; set flag
  252.         jmp    @@NoTrans        ; otherwise shut down sending
  253. @@OkToSend:
  254.     or    cs:busyflag, BUSY2SEND    ; set flag
  255.         mov    bx, cs:one_in_tail    ; set index
  256.         cmp    bx, cs:one_in_head    ; are chars to send?
  257.         je    @@NoTrans        ; if not, shut down sending
  258.         mov    al, cs:one_in + bx    ; else move char to AL
  259.         mov    dx, COM2BASE
  260.         out    dx, al
  261.         inc    cs:one_in_tail            ; increment index
  262.         test    cs:one_in_tail, BUFFERLENMASK    ; check for overflow
  263.         jz    @@SentOK            ; if no overflow, jump
  264.         mov    cs:one_in_tail, 0    ; else zero index
  265.         jmp    @@SentOK        ; and jump
  266. @@SentOK:
  267.     xor    cs:busyflag, BUSY2SEND    ; reset flag
  268.         jmp    @@SendEOI
  269. @@NoTrans:
  270.     mov    dx, COM2IER        ; read interrupt enable
  271.         in    al, dx
  272.         cmp    al, RDAENABLE        ; RDA only already?
  273.         je    @@NoTrans2        ; if so, do nothing
  274.         mov    al, RDAENABLE        ; else enable RDA only
  275.         out    dx, al
  276.         jmp    @@NoTrans2        ; and jump
  277. @@NoTrans2:
  278.     xor    cs:busyflag, BUSY2SEND    ; reset flag
  279.         jmp    @@SendEOI        ; and jump
  280.  
  281. @@NotOurs:
  282.     test    cs:chain, 0FFh        ; is chain zero?
  283.         jz    @@SendEOI        ; if so, return normally
  284.         pushf                ; preserve flags
  285.         call    cs:old_int_B        ; call old handler
  286.         jmp    @@Final            ; and return
  287.  
  288. @@SendEOI:
  289.     mov    al, EOI            ; send EOI
  290.         out    EOIPORT, al
  291.  
  292. @@Final:
  293.     pop    dx            ; restore
  294.         pop    bx
  295.         pop    ax
  296.         iret                ; return
  297.  
  298.  
  299. ; SIGNATURE USED FOR INSTALLATION CHECK
  300.  
  301. signature    db    'JWBA12'
  302.  
  303.  
  304. ; INTERFACE INTERRUPT HANDLER -- RETURNS POINTER TO DATA AREA
  305.  
  306. Interface:
  307.     mov    ax, cs            ; put segment in AX
  308.         mov    bx, offset errors    ; put offset in BX
  309.         iret                ; and return
  310.  
  311.  
  312. ; INSTALLATION CODE -- IS DISCARDED AFTER INSTALLATION
  313.  
  314. Last_byte:
  315.  
  316. OKmessage    db    'AQUEDUCT installed OK.',0Dh,0Ah,'$'
  317. FAILmessage    db    'AQUEDUCT installation error.',0Dh,0Ah,'$'
  318. COPYRIGHT    db    'Copyright (c) 1990 James W. Birdsall.'
  319. COPYRIGHT2    db    'All Rights Reserved.'
  320.  
  321. Install:
  322.     mov    bx, es            ; copy PSP segment from ES to BX
  323.         mov    PSPseg, bx        ; put into storage
  324.         mov    si, ENVOFFSET
  325.         mov    ax, es:si        ; move environment segment into AX
  326.         or    ax, ax            ; check it
  327.         jz    Continue        ; if zero, no environment
  328.         mov    es, ax            ; put env seg in ES
  329.         mov    ah, 49h            ; free block
  330.         int    21h
  331.         jc    Fail            ; if carry set, error
  332. Continue:
  333.                     ; put far ptrs to handlers in storage
  334.     mov    WORD PTR [int_B], offset Com2handler
  335.         mov    WORD PTR [int_C], offset Com1handler
  336.         mov    ax, cs
  337.         mov    WORD PTR [int_B+2], ax
  338.         mov    WORD PTR [int_C+2], ax
  339.  
  340.         mov    ah, 35h                ; get old int 0Bh vector
  341.         mov    al, 0Bh
  342.         int    21h
  343.         mov    WORD PTR [old_int_B], bx    ; and put in old_int_B
  344.         mov    bx, es
  345.         mov    WORD PTR [old_int_B+2], bx
  346.  
  347.         mov    ah, 35h                ; get old int 0Ch vector
  348.         mov    al, 0Ch
  349.         int    21h
  350.         mov    WORD PTR [old_int_C], bx    ; and put in old_int_C
  351.         mov    bx, es
  352.         mov    WORD PTR [old_int_C+2], bx
  353.  
  354.         mov    ah, 35h                ; get old interface vector
  355.         mov    al, INTERFACEINT
  356.         int    21h
  357.         mov    WORD PTR [old_interface], bx    ; and put in old_interface
  358.         mov    bx, es
  359.         mov    WORD PTR [old_interface+2], bx
  360.         mov    ah, 25h                ; set up interface
  361.         mov    al, INTERFACEINT
  362.         mov    dx, offset Interface
  363.         int    21h
  364.  
  365.         mov    ah, 09h                ; print OK message
  366.         mov    dx, offset OKmessage
  367.         int    21h
  368.  
  369.         mov    dx, offset Last_byte        ; go resident with code 0
  370.         add    dx, 15
  371.         mov    cl, 4
  372.         shr    dx, cl
  373.         mov    ah, 31h
  374.         xor    al, al
  375.         int    21h
  376. Fail:
  377.     mov    ah, 09h                ; print FAIL message
  378.         mov    dx, offset FAILmessage
  379.         int    21h
  380.  
  381.     mov    ah, 4Ch                ; exit with code 3
  382.         mov    al, 3
  383.         int    21h
  384.         END     start
  385. END
  386.